module mculib.arm.cortex_m4.crc;

import std.traits:isScalarType;

import std.bitmanip;

import mculib.chip;
import mculib.arm.rcc;




static if(!HasPeriph!("CRC"))
    public import mculib.arm.common.crc:crc32Of;
    
uint crc32Of(T)(T* data,size_t len) 
if(isScalarType!T && HasPeriph!("CRC")) 
{
    enum CRC_EN_Name = "CRCEN";
    
    if(Peripherals.CRC.IDR.IDR !=0)
    {
        return uint.max;
    }

    Peripherals.CRC.IDR.IDR = 1;
    scope(exit) 
    {
        Peripherals.CRC.IDR.IDR = 0;
        DRCC.enable!CRC_EN_Name = false;
    }
    DRCC.enable!CRC_EN_Name = true;

    /// 重置CRC
    Peripherals.CRC.CR.CR = true;

    static if(T.sizeof == uint.sizeof)
    {
        while(len--)
        {
            Peripherals.CRC.DR.DR = *data++;
        }
    }
    else
    {
        // 全长
        auto nlen = len * T.sizeof;
        // 按4字节对齐长度
        auto ilen = nlen / uint.sizeof;
        // 余数
        auto blen = nlen % uint.sizeof;

        auto pdata = cast(ubyte*)data;

        /// 处理4字节uint32
        while(ilen--)
        {
            Peripherals.CRC.DR.DR = *cast(uint*)pdata;
            pdata += uint.sizeof;
        }

        // 处理剩余字节
        uint last = *cast(uint*)pdata;
        // 
        /// 保留last中有效数据位
        last &= (uint.max >> (uint.sizeof - blen) * 8);

        /// 把最后一个32位送入
        Peripherals.CRC.DR.DR = last;

    }



    return Peripherals.CRC.DR.DR() ^ uint.max;
    
}